<template>
  <div class="left">
    <el-button :loading="loading" type="primary" @click="handleUpload"
      >点击上传</el-button
    >
    <input
      type="file"
      ref="excelUploadInput"
      class="excel-upload-input"
      accept=".xlsx,.xls"
      @change="handleChange"
    />
  </div>
</template>

<script setup>
import { ref, defineProps } from 'vue'
import XLSX from 'xlsx'
import { getHeaderRow } from './utils'
const props = defineProps({
  beforeUpload: {
    type: Function
  },
  onSuccess: {
    type: Function
  }
})
const loading = ref(false)
const excelUploadInput = ref(null)
// 点击上传按钮，出发input点击
const handleUpload = () => {
  excelUploadInput.value.click()
}
// 监听选中文件操作
const handleChange = (e) => {
  const file = e.target.files[0]
  // 如果没有指定上传前的回调的话，直接调用读取文件操作
  if (!props.beforeUpload) {
    readFileFn(file)
    return false
  }
  // 如果指定了上传前的回调的话，只有返回true时才调用读取文件操作
  const flag = props.beforeUpload(file)
  if (flag) {
    readFileFn(file)
  }
}

// 读取文件
const readFileFn = (file) => {
  return new Promise((resolve, reject) => {
    loading.value = true
    const render = new FileReader()
    render.onload = (e) => {
      // 1、获取解析后的数据
      const data = e.target.result
      // 2、利用XLSX对数据进行解析
      const workbook = XLSX.read(data, { type: 'array' })
      // 3、获取第一张表格（工作簿）名称
      const firstSheetName = workbook.SheetNames[0]
      // 4、读取sheet1（第一张表格的数据
      const workSheet = workbook.Sheets[firstSheetName]
      // 5、解析数据表头
      const header = getHeaderRow(workSheet)
      // 6、解析数据体
      const results = XLSX.utils.sheet_to_json(workSheet)
      // 7、传入解析之后的数据
      generateData({ header, results })
      // 8、处理loading
      loading.value = false
      // 9、成功回调
      resolve()
    }
    render.readAsArrayBuffer(file)
  })
}

// 导入内容生成数据
const generateData = (excelData) => {
  props.onSuccess && props.onSuccess(excelData)
}
</script>

<style lang="scss" scoped>
.left {
  flex: 1;
  max-width: 500px;
  @include flex-center;
  border: 2px dotted #ddd;
  border-radius: 6px;
  .excel-upload-input {
    display: none;
  }
}
</style>
